package com.gopay.bis.ccb.cbrmb.operation;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Calendar;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.ccb.cbrmb.req.CbRmbNotificationMsg;
import com.gopay.common.domain.bank.ccb.cbrmb.req.CbRmbQueryReqMsg;
import com.gopay.common.domain.bank.ccb.cbrmb.res.CbRmbQueryRespMsg;
import com.gopay.common.domain.bank.ccb.cbrmb.res.CbRmbResponseMsg;
import com.gopay.common.exception.GopayException;

public class CbRmbSocketTransportImpl {
	
	private Map<String, String> cbrConfig;

    public Logger logger = LoggerFactory.getLogger(CbRmbSocketTransportImpl.class);

    public CbRmbResponseMsg submit(CbRmbNotificationMsg msg) throws GopayException {

        logger.error("=========this is bis bank submit =============++IP"+cbrConfig.get("ccb.socket.ip"));
        Socket socket = null;
        InputStream is = null;
        OutputStream os = null;
        CbRmbResponseMsg res = null;
        try {
            socket = new Socket(cbrConfig.get("ccb.socket.ip"), Integer.valueOf(cbrConfig.get("ccb.socket.port") ));
            socket.setKeepAlive(true);
            os = socket.getOutputStream();
            byte[] dataByte = msg.getByteData();
            os.write(dataByte);
            os.flush();
            is = socket.getInputStream();
            byte[] source = toByteArray(is);
            logger.error(" 通知银行返回信息：" + source.length);
            res = new CbRmbResponseMsg(source);
            logger.error(" 通知银行返回信息：" + ToStringBuilder.reflectionToString(res));
        } catch (Exception e) {
            logger.error(" 和银行通信出现问题" + e.getMessage());
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E5322);
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                }
            }
            if (null != socket) {
                try {
                    socket.close();
                } catch (IOException e) {
                }
            }
        }
        return res;
    }
    
    
    public CbRmbQueryRespMsg query(CbRmbQueryReqMsg reqMsg) throws GopayException {
        logger.error("=========this is bis bank query =============++IP"+cbrConfig.get("ccb.socket.ip"));
        Socket socket = null;
        InputStream is = null;
        OutputStream os = null;
        CbRmbQueryRespMsg res = null;
        try {
            socket = new Socket(cbrConfig.get("ccb.socket.ip"), Integer.valueOf(cbrConfig.get("ccb.socket.port") ));
            socket.setKeepAlive(true);
            os = socket.getOutputStream();
            byte[] dataByte = reqMsg.getByteData();
            os.write(dataByte);
            os.flush();
            is = socket.getInputStream();
            byte[] source = toByteArray(is);
            logger.error(" 查询银行返回信息：" + source.length);
            res = new CbRmbQueryRespMsg(source);
            logger.error(" 查询银行返回信息：" + ToStringBuilder.reflectionToString(res));
        } catch (Exception e) {
            logger.error(" 和银行通信出现问题" + e.getMessage());
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E5322);
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                }
            }
            if (null != socket) {
                try {
                    socket.close();
                } catch (IOException e) {
                }
            }
        }
        return res;
    }
    
    /**
     * this method no syn
     * @param inputStream
     * @return
     * @throws GopayException
     */
    @Deprecated
    public byte[] getAvailableBytes(InputStream inputStream) throws GopayException {
        Calendar cal = Calendar.getInstance();
        long startMillis = cal.getTimeInMillis();
        long endMillis = startMillis;
        int timeout = 60;
        int count = 0;
        try {
            while (count == 0 && (endMillis - startMillis) <= timeout * 1000) {
                endMillis = Calendar.getInstance().getTimeInMillis();
                count = inputStream.available();
            }
            if (count == 0 && (endMillis - startMillis) > timeout * 1000) {
                logger.error("read server response time out !");
            }
            byte[] bytes = new byte[count];
            int readCount = 0; // 已经成功读取的字节的个数
            while (readCount < count) {
                readCount += inputStream.read(bytes, readCount, count - readCount);
            }
            logger.error("==============back:" + new String(bytes, "GBK"));
            return bytes;
        } catch (Exception e) {
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E5322);
        }
    }
    
    public byte[] toByteArray(InputStream input) throws GopayException {
        try {
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            byte[] buffer = new byte[4096];
            int n = 0;
            while (-1 != (n = input.read(buffer))) {
                output.write(buffer, 0, n);
            }
            logger.error("==============back:" + new String(output.toByteArray(), "GBK"));
            return output.toByteArray();
        } catch (Exception e) {
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E5322);
        }
    }

	public Map<String, String> getCbrConfig() {
		return cbrConfig;
	}

	public void setCbrConfig(Map<String, String> cbrConfig) {
		this.cbrConfig = cbrConfig;
	}
}
